home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume22 / psutils / part01 next >
Encoding:
Text File  |  1991-09-04  |  58.6 KB  |  2,280 lines

  1. Newsgroups: comp.sources.misc
  2. From: Angus Duggan <ajcd@dcs.ed.ac.uk>
  3. Subject:  v22i087:  psutils - Postscript document manipulation tools, Part01/02
  4. Message-ID: <csm-v22i087=psutils.220703@sparky.imd.sterling.com>
  5. X-Md4-Signature: e992925b7bd94bc0709e9a9299e11754
  6. Date: Wed, 4 Sep 1991 03:08:36 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Angus Duggan <ajcd@dcs.ed.ac.uk>
  10. Posting-number: Volume 22, Issue 87
  11. Archive-name: psutils/part01
  12. Environment: UNIX
  13.  
  14. This is the first of a two part shar file which contains a set of
  15. PostScript  tools  which  I have found useful over the last year; 
  16. utilities for extracting  and  rearranging pages,  and for fixing 
  17. various non-conforming PostScript  files.    Page  selection  and 
  18. rearrangement are supported, including arrangement into signatures 
  19. for booklet printing, and page merging for 2up/4up/8up/9up printing.
  20.  
  21. These  utilities  have  been  compiled  and run  on Sun-3 and Sun-4
  22. machines under  SunOS 4.1.1  and 4.0.1,  and on HP9000/375 machines 
  23. under HPUX 7.0 and should work on others as well.
  24.  
  25. PROGRAMS:
  26. psbook          rearranges pages into signatures
  27. psselect        selects pages and page ranges
  28. pstops          performs general page rearrangement and selection
  29. psnup           uses pstops to merge multiple pages per sheet
  30. epsffit         fits an EPSF file to a given bounding box
  31.  
  32. SCRIPTS:
  33. getafm   (sh)   outputs PostScript to retrieve AFM file from printer
  34. showchar (sh)   outputs PostScript to draw a character with metric info
  35. fixfmps  (perl) filter to fix framemaker documents so that psselect etc. work
  36. fixmacps (perl) filter to fix Macintosh documents with saner version of md
  37. fixpspps (perl) filter to fix PSPrint PostScript so that psselect etc. work
  38.  
  39. Bug fixes and suggestions to ajcd@dcs.ed.ac.uk
  40.  
  41. Angus Duggan
  42. ----
  43. #! /bin/sh
  44. # This is a shell archive.  Remove anything before this line, then unpack
  45. # it by saving it into a file and typing "sh file".  To overwrite existing
  46. # files, type "sh file -c".  You can also feed this as standard input via
  47. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  48. # will see the following message at the end:
  49. #        "End of archive 1 (of 2)."
  50. # Contents:  Makefile README epsffit.c fixfmps fixmacps fixpspps getafm
  51. #   psbook.1 psbook.c psnup psnup.1 psselect.1 psselect.c pstops.1
  52. #   pstops.c psutil.c psutil.h showchar
  53. # Wrapped by ajcd@carna on Tue Sep  3 10:38:54 1991
  54. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  55. if test -f Makefile -a "${1}" != "-c" ; then 
  56.   echo shar: Will not over-write existing file \"Makefile\"
  57. else
  58. echo shar: Extracting \"Makefile\" \(643 characters\)
  59. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  60. X# Makefile for PS utilities
  61. X
  62. XCFLAGS=-O
  63. X
  64. X# epsffit fits an epsf file to a given bounding box
  65. X# psbook rearranges pages into signatures
  66. X# psselect selects page ranges
  67. X# pstops performs general page rearrangement and merging
  68. X
  69. Xall: psbook psselect pstops epsffit
  70. X
  71. Xepsffit: epsffit.c
  72. X    $(CC) $(CFLAGS) -o epsffit epsffit.c
  73. X
  74. Xpsbook: psbook.o psutil.o
  75. X    $(CC) -o psbook psutil.o psbook.o
  76. X
  77. Xpsselect: psselect.o psutil.o
  78. X    $(CC) -o psselect psutil.o psselect.o
  79. X
  80. Xpstops: pstops.o psutil.o
  81. X    $(CC) -o pstops psutil.o pstops.o
  82. X
  83. Xpsbook.c: psutil.h
  84. X
  85. Xpstops.c: psutil.h
  86. X
  87. Xpsutil.c: psutil.h
  88. X
  89. Xpsselect.c: psutil.h
  90. X
  91. Xclean:
  92. X    rm -f *.o psbook psselect pstops epsffit
  93. END_OF_Makefile
  94. if test 643 -ne `wc -c <Makefile`; then
  95.     echo shar: \"Makefile\" unpacked with wrong size!
  96. fi
  97. # end of overwriting check
  98. fi
  99. if test -f README -a "${1}" != "-c" ; then 
  100.   echo shar: Will not over-write existing file \"README\"
  101. else
  102. echo shar: Extracting \"README\" \(2819 characters\)
  103. sed "s/^X//" >README <<'END_OF_README'
  104. XPostScript Utilities            Angus Duggan        3 September 1991
  105. X
  106. XThis shar file contains some utilities for manipulating PostScript documents.
  107. XPage selection and rearrangement are supported, including arrangement into
  108. Xsignatures for booklet printing, and page merging for 2up/4up/8up/9up printing.
  109. X
  110. XENVIRONMENT
  111. X
  112. XThese utilities have been compiled and run on Sun-3 and Sun-4 machines under
  113. XSunOS 4.1.1 and 4.0.1, and on HP9000/375 machines under HPUX 7.0
  114. X
  115. XFILES
  116. X
  117. XThe files contained are:
  118. X
  119. X-rw-r--r--  1 ajcd          643 Jul 12 10:34 Makefile
  120. X-rw-r--r--  1 ajcd         2819 Sep  3 10:35 README
  121. X-rw-r--r--  1 ajcd        42765 Sep  3 10:07 appledict.ps.uue
  122. X-rw-r--r--  1 ajcd         3673 Jul 12 10:34 epsffit.c
  123. X-rwxr-xr-x  1 ajcd          359 Jul 16 15:21 fixfmps
  124. X-rwxr-xr-x  1 ajcd         1042 Jul 16 15:21 fixmacps
  125. X-rwxr-xr-x  1 ajcd         1165 Jul 16 15:21 fixpspps
  126. X-rwxr-xr-x  1 ajcd         4706 Sep  3 10:22 getafm
  127. X-rw-r--r--  1 ajcd         1066 Jul 12 10:34 psbook.1
  128. X-rw-r--r--  1 ajcd         1990 Jul 12 10:34 psbook.c
  129. X-rwxr-xr-x  1 ajcd         2113 Jul 12 10:34 psnup
  130. X-rw-r--r--  1 ajcd         2146 Jul 12 10:34 psnup.1
  131. X-rw-r--r--  1 ajcd         1509 Jul 12 10:34 psselect.1
  132. X-rw-r--r--  1 ajcd         4621 Jul 12 10:34 psselect.c
  133. X-rw-r--r--  1 ajcd         3227 Jul 12 10:34 pstops.1
  134. X-rw-r--r--  1 ajcd         9273 Jul 12 10:34 pstops.c
  135. X-rw-r--r--  1 ajcd         5220 Jul 12 10:34 psutil.c
  136. X-rw-r--r--  1 ajcd          663 Jul 12 10:34 psutil.h
  137. X-rwxr-xr-x  1 ajcd         2472 Sep  3 10:38 showchar
  138. X
  139. XPROGRAMS
  140. X
  141. Xpsbook          rearranges pages into signatures
  142. Xpsselect        selects pages and page ranges
  143. Xpstops          performs general page rearrangement and selection
  144. Xpsnup           uses pstops to merge multiple pages per sheet
  145. Xepsffit         fits an EPSF file to a given bounding box
  146. X
  147. Xpsselect in modeled after Chris Torek's dviselect program, and psbook is
  148. Xmodeled after Tom Rokicki's dvidvi program. psbook is modeled on my own
  149. Xdvibook program, which borrows heavily from Chris Torek's dviselect.
  150. X
  151. XSCRIPTS
  152. X
  153. Xgetafm   (sh)   outputs PostScript to retrieve AFM file from printer
  154. Xshowchar (sh)   outputs PostScript to draw a character with metric info
  155. Xfixfmps  (perl) filter to fix framemaker documents so that psselect etc. work
  156. Xfixmacps (perl) filter to fix Macintosh documents with saner version of md
  157. Xfixpspps (perl) filter to fix PSPrint PostScript so that psselect etc. work
  158. X
  159. XINSTALLATION
  160. X
  161. XUUdecode appledict.ps.uue, edit Makefile to put in required CFLAGS (SYSV for
  162. XSystem V machines), "make", and install files in appropriate places.
  163. X
  164. XBUGS
  165. X
  166. XThe utilities don't check for PS-Adobe-?.? conformance; they assume documents
  167. Xconform. Utilities need an extra save/restore around whole document on a
  168. XSPARCPrinter, because of bugs in the xnews server.
  169. X
  170. XBug fixes and suggestions to ajcd@dcs.ed.ac.uk
  171. END_OF_README
  172. if test 2819 -ne `wc -c <README`; then
  173.     echo shar: \"README\" unpacked with wrong size!
  174. fi
  175. # end of overwriting check
  176. fi
  177. if test -f epsffit.c -a "${1}" != "-c" ; then 
  178.   echo shar: Will not over-write existing file \"epsffit.c\"
  179. else
  180. echo shar: Extracting \"epsffit.c\" \(3673 characters\)
  181. sed "s/^X//" >epsffit.c <<'END_OF_epsffit.c'
  182. X/* epsffit.c
  183. X * AJCD 6 Dec 90
  184. X * fit epsf file into constrained size
  185. X * Usage:
  186. X *       epsffit [-c] [-r] [-a] [-s] llx lly urx ury
  187. X *               -c centres the image in the bounding box given
  188. X *               -r rotates the image by 90 degrees anti-clockwise
  189. X *               -a alters the aspect ratio to fit the bounding box
  190. X *               -s adds a showpage at the end of the image
  191. X */
  192. X
  193. X#include <stdio.h>
  194. X#include <ctype.h>
  195. X
  196. X#define min(x,y) ((x) > (y) ? (y) : (x))
  197. X#define max(x,y) ((x) > (y) ? (x) : (y))
  198. X
  199. Xstatic char *prog;
  200. X
  201. Xusage()
  202. X{
  203. X   fprintf(stderr, "Usage: %s [-c] [-r] [-a] [-s] llx lly urx ury\n", prog);
  204. X   exit(1);
  205. X}
  206. X
  207. Xmain(argc, argv)
  208. X     int argc;
  209. X     char **argv;
  210. X{
  211. X   int fit[4], i;
  212. X   int bbfound = 0;              /* %%BoundingBox: found */
  213. X   int urx, ury, llx, lly;
  214. X   int furx, fury, fllx, flly, fwidth, fheight;
  215. X   int showpage = 0, centre = 0, rotate = 0, aspect = 0;
  216. X   char buf[BUFSIZ];
  217. X
  218. X   prog = *argv++; argc--;
  219. X
  220. X   while (argc > 0 && argv[0][0] == '-') {
  221. X      switch (argv[0][1]) {
  222. X      case 'c': centre = 1; break;
  223. X      case 's': showpage = 1; break;
  224. X      case 'r': rotate = 1; break;
  225. X      case 'a': aspect = 1; break;
  226. X      default:  usage();
  227. X      }
  228. X      argc--;
  229. X      argv++;
  230. X   }
  231. X
  232. X   if (argc != 4) usage();
  233. X   fllx = atoi(argv[0]);
  234. X   flly = atoi(argv[1]);
  235. X   furx = atoi(argv[2]);
  236. X   fury = atoi(argv[3]);
  237. X   if (rotate) {
  238. X      fwidth = fury - flly;
  239. X      fheight = furx - fllx;
  240. X   } else {
  241. X      fwidth = furx - fllx;
  242. X      fheight = fury - flly;
  243. X   }
  244. X
  245. X   while (fgets(buf, BUFSIZ, stdin)) {
  246. X      if (buf[0] == '%' && (buf[1] == '%' || buf[1] == '!')) {
  247. X     /* still in comment section */
  248. X     if (!strncmp(buf, "%%BoundingBox:", 14)) {
  249. X        if (sscanf(buf, "%%%%BoundingBox:%d %d %d %d\n",
  250. X               &llx, &lly, &urx, &ury) == 4)
  251. X           bbfound = 1;
  252. X     } else if (!strncmp(buf, "%%EndComments", 13)) {
  253. X        strcpy(buf, "\n"); /* don't repeat %%EndComments */
  254. X        break;
  255. X     } else fputs(buf,stdout);
  256. X      } else break;
  257. X   }
  258. X   if (bbfound) { /* put BB, followed by scale&translate */
  259. X      double width = urx-llx, height = ury-lly;
  260. X      double xscale = fwidth/width, yscale = fheight/height;
  261. X      double xoffset = fllx, yoffset = flly;
  262. X      if (!aspect) {       /* preserve aspect ratio ? */
  263. X     xscale = yscale = min(xscale,yscale);
  264. X      }
  265. X      width *= xscale;     /* actual width and height after scaling */
  266. X      height *= yscale;
  267. X      if (centre) {
  268. X     if (rotate) {
  269. X        xoffset += (fheight - height)/2;
  270. X        yoffset += (fwidth - width)/2;
  271. X     } else {
  272. X        xoffset += (fwidth - width)/2;
  273. X        yoffset += (fheight - height)/2;
  274. X     }
  275. X      }
  276. X      printf("%%%%BoundingBox: %d %d %d %d\n", (int)xoffset, (int)yoffset,
  277. X         (int)(xoffset+(rotate ? height : width)),
  278. X         (int)(yoffset+(rotate ? width : height)));
  279. X      if (rotate) {  /* compensate for original image shift */
  280. X     xoffset += height + lly * yscale;  /* displacement for rotation */
  281. X     yoffset -= llx * xscale;
  282. X      } else {
  283. X     xoffset -= llx * xscale;
  284. X     yoffset -= lly * yscale;
  285. X      }
  286. X      puts("%%EndComments");
  287. X      if (showpage)
  288. X     puts("save /showpage{}def /copypage{}def /erasepage{}def");
  289. X      else
  290. X     puts("%%BeginProcSet: epsffit 1 0");
  291. X      puts("gsave");
  292. X      printf("%.3lf %.3lf translate\n", xoffset, yoffset);
  293. X      if (rotate)
  294. X     puts("90 rotate");
  295. X      printf("%.3lf %.3lf scale\n", xscale, yscale);
  296. X      if (!showpage)
  297. X     puts("%%EndProcSet");
  298. X   }
  299. X   do {
  300. X      fputs(buf,stdout);
  301. X   } while (fgets(buf, BUFSIZ, stdin));
  302. X   if (bbfound) {
  303. X      puts("grestore");
  304. X      if (showpage)
  305. X     puts("restore showpage"); /* just in case */
  306. X   } else {
  307. X      fprintf(stderr, "%s: no %%%%BoundingBox:\n", prog);
  308. X      exit(1);
  309. X   }
  310. X   exit(0);
  311. X}
  312. END_OF_epsffit.c
  313. if test 3673 -ne `wc -c <epsffit.c`; then
  314.     echo shar: \"epsffit.c\" unpacked with wrong size!
  315. fi
  316. # end of overwriting check
  317. fi
  318. if test -f fixfmps -a "${1}" != "-c" ; then 
  319.   echo shar: Will not over-write existing file \"fixfmps\"
  320. else
  321. echo shar: Extracting \"fixfmps\" \(359 characters\)
  322. sed "s/^X//" >fixfmps <<'END_OF_fixfmps'
  323. X#!/usr/local/bin/perl
  324. X# fmps: get conforming PostScript out of FrameMaker file
  325. X# move all FMDEFINEFONTs to start of pages
  326. X
  327. X%fonts=();
  328. X
  329. Xwhile (<>) {
  330. X   if (/^([0-9]+) [0-9]+ .* FMDEFINEFONT$/) {
  331. X      $fonts{$1} = $_;
  332. X   } elsif (/^[0-9]+ [0-9]+ [0-9]+ FMBEGINPAGE$/) {
  333. X      print STDOUT $_, join('',values(%fonts));
  334. X   } else {
  335. X      print STDOUT $_;
  336. X   }
  337. X}
  338. END_OF_fixfmps
  339. if test 359 -ne `wc -c <fixfmps`; then
  340.     echo shar: \"fixfmps\" unpacked with wrong size!
  341. fi
  342. chmod +x fixfmps
  343. # end of overwriting check
  344. fi
  345. if test -f fixmacps -a "${1}" != "-c" ; then 
  346.   echo shar: Will not over-write existing file \"fixmacps\"
  347. else
  348. echo shar: Extracting \"fixmacps\" \(1042 characters\)
  349. sed "s/^X//" >fixmacps <<'END_OF_fixmacps'
  350. X#!/usr/local/bin/perl
  351. X
  352. X$line = 0;            # keep line count
  353. X$sane = "appledict.ps";
  354. X
  355. Xwhile ($_ = shift(@ARGV)) {
  356. X   if (/^-a(ppledict)?$/)   { $sane = shift(@ARGV); }
  357. X   else {
  358. X      unshift(@ARGV, $_);
  359. X      last;
  360. X   }
  361. X}
  362. X
  363. Xopen(SANE, "<$sane");
  364. X$sane_v = <SANE>;
  365. X($sane_n, $sane_r) =
  366. X   $sane_v =~ /^%%BeginProcSet: "\(AppleDict md\)" ([0-9]+) ([0-9]+)$/;
  367. X
  368. Xwhile (<>) {
  369. X   if (/^%!/) {
  370. X      if (! $line) {
  371. X     print;
  372. X      }
  373. X   } elsif (/^%%BeginProcSet: "\(AppleDict md\)" ([0-9]+) ([0-9]+)$/) {
  374. X      if ($1 == $sane_n && $2 == $sane_r) {
  375. X     $ignore = 1;
  376. X      } else {
  377. X     printf STDERR "Unrecognised AppleDict version %d %d\n", $1, $2;
  378. X     if (! $line) {
  379. X        print "%!\n";
  380. X     }
  381. X     print;
  382. X      }
  383. X   } elsif (/%%EndProcSet/) {
  384. X      if ($ignore) {
  385. X     $ignore = 0;
  386. X     if (! $line) {
  387. X        print "%!\n";
  388. X     }
  389. X     print $sane_v;
  390. X     while(<SANE>) {
  391. X        print;
  392. X     }
  393. X      } else {
  394. X     if (! $line) {
  395. X        print "%!\n";
  396. X     }
  397. X     print;
  398. X      }
  399. X   } else {
  400. X      if (! $ignore) {
  401. X     if (! $line) {
  402. X        print "%!\n";
  403. X     }
  404. X     print;
  405. X      }
  406. X   }
  407. X   $line++;
  408. X}
  409. Xclose(<SANE>);
  410. END_OF_fixmacps
  411. if test 1042 -ne `wc -c <fixmacps`; then
  412.     echo shar: \"fixmacps\" unpacked with wrong size!
  413. fi
  414. chmod +x fixmacps
  415. # end of overwriting check
  416. fi
  417. if test -f fixpspps -a "${1}" != "-c" ; then 
  418.   echo shar: Will not over-write existing file \"fixpspps\"
  419. else
  420. echo shar: Extracting \"fixpspps\" \(1165 characters\)
  421. sed "s/^X//" >fixpspps <<'END_OF_fixpspps'
  422. X#!/usr/local/bin/perl
  423. X# mangle PostScript produced by PSPrint to make it almost conforming
  424. X
  425. X$header = 1; $ignore = 0;
  426. X$verbose = 0;
  427. X@body = ();
  428. X%fonts = (); $font = "";
  429. X$inchar = 0; @char = ();
  430. X
  431. Xwhile (<>) {
  432. X   if (/^@end$/) {
  433. X      $ignore = 1;
  434. X   } elsif (/^[0-9]+ @bop0$/) {
  435. X      $ignore = 0;
  436. X      $header = 1;
  437. X   } elsif ($header) {
  438. X      if (/^\/([a-z.0-9]+) @newfont$/) {
  439. X     if (! defined($fonts{$1})) {
  440. X        $fonts{$1} = 1;
  441. X        print;
  442. X     } elsif ($verbose) {
  443. X        print STDERR "$font already defined\n";
  444. X     }
  445. X      } elsif (/^([a-z.0-9]+) sf$/) {
  446. X     $font = $1;
  447. X     print;
  448. X      } elsif (/^\[</) {
  449. X     $inchar = 1;
  450. X     push (@char, $_);
  451. X      } elsif ($inchar) {
  452. X     push (@char, $_);
  453. X     if (/.*\] ([0-9]+) dc$/) {
  454. X        if (! defined($fonts{$font,$1})) {
  455. X           $fonts{$font,$1} = 1;
  456. X           print (@char);
  457. X        } elsif ($verbose) {
  458. X           print STDERR "$font character $1 already defined\n";
  459. X        }
  460. X        $inchar = 0;
  461. X        @char = ();
  462. X     }
  463. X      } elsif (/^([0-9]+) @bop1$/) {
  464. X     $header = 0;
  465. X     push (@body, "%%Page: ? $1\n");
  466. X     push (@body, $_);
  467. X      } else {
  468. X     print;
  469. X      }
  470. X   } elsif (! $ignore) {
  471. X      push (@body, $_);
  472. X   }
  473. X}
  474. Xprint (@body);
  475. Xprint ("@end\n");
  476. END_OF_fixpspps
  477. if test 1165 -ne `wc -c <fixpspps`; then
  478.     echo shar: \"fixpspps\" unpacked with wrong size!
  479. fi
  480. chmod +x fixpspps
  481. # end of overwriting check
  482. fi
  483. if test -f getafm -a "${1}" != "-c" ; then 
  484.   echo shar: Will not over-write existing file \"getafm\"
  485. else
  486. echo shar: Extracting \"getafm\" \(4706 characters\)
  487. sed "s/^X//" >getafm <<'END_OF_getafm'
  488. X#!/bin/sh
  489. X# getafm: get afm file from printer
  490. X#         Note that the AFM file returned will not have any kerning
  491. X#         information, but it is useful if you can't get the file anywhere else
  492. X# usage:
  493. X#       getafm Font-Name | lpr -Pprinter
  494. X
  495. Xif [ $# != 1 ]; then
  496. X        echo "Usage: `basename $0` Font-Name" >&2
  497. X        exit 1
  498. Xfi
  499. X
  500. Xcat <<EOF
  501. X%!
  502. X% Get character metrics and bounding box for $1
  503. X/ns 30 string def
  504. X/fname /$1 def
  505. X/fn fname findfont 1000 scalefont def
  506. X/en fn /Encoding get def
  507. Xfn setfont
  508. X
  509. X/sp { ( )print } def
  510. X/nl { (\n)print } def
  511. X/pn { ns cvs print } def
  512. X
  513. X/printbb { % llx lly urx ury => -
  514. X   4 -1 roll round cvi pn sp
  515. X   3 -1 roll round cvi pn sp
  516. X   exch round cvi pn sp
  517. X   round cvi pn
  518. X} def
  519. X
  520. X(StartFontMetrics 2.0\n)print
  521. X(Comment Created by `basename $0` 1.00 (c) AJCD `date`\n)print
  522. Xfn /FontName known {
  523. X   (FontName )print fn /FontName get pn nl
  524. X} {
  525. X   (FontName $1\n) print
  526. X} ifelse
  527. Xen StandardEncoding eq {
  528. X   (EncodingScheme AdobeStandardEncoding\n)print
  529. X} {
  530. X   en ISOLatin1Encoding eq {
  531. X      (EncodingScheme ISOLatin1Encoding\n)print
  532. X   } if
  533. X} ifelse
  534. Xfn /FontInfo known {
  535. X   fn /FontInfo get
  536. X   dup /FamilyName known {
  537. X      (FamilyName )print dup /FamilyName get print nl
  538. X   } if
  539. X   dup /FullName known {
  540. X      (FullName )print dup /FullName get print nl
  541. X   } if
  542. X   dup /Notice known {
  543. X      (Notice )print dup /Notice get print nl
  544. X   } if
  545. X   dup /Weight known {
  546. X      (Weight )print dup /Weight get print nl
  547. X   } if
  548. X   dup /Version known {
  549. X      (Version )print dup /Version get print nl
  550. X   } if
  551. X   dup /ItalicAngle known {
  552. X      (ItalicAngle )print dup /ItalicAngle get pn nl
  553. X   } if
  554. X   dup /isFixedPitch known {
  555. X      (IsFixedPitch )print dup /isFixedPitch get {(true)}{(false)}ifelse print
  556. X       nl
  557. X   } {
  558. X      (IsFixedPitch false\n)print
  559. X   } ifelse
  560. X   dup /UnderlinePosition known {
  561. X      (UnderlinePosition )print dup /UnderlinePosition get pn nl
  562. X   } if
  563. X   dup /UnderlineThickness known {
  564. X      (UnderlineThickness )print dup /UnderlineThickness get pn nl
  565. X   } if
  566. X   pop
  567. X} if
  568. X(FontBBox )print fn /FontBBox get aload pop printbb nl
  569. X
  570. X%CapHeight 662
  571. X%XHeight 448
  572. X%Descender -217
  573. X%Ascender 682
  574. X%(PaintType: )print fn /PaintType get pn (\n) print flush
  575. X
  576. X(StartCharMetrics )print
  577. Xfn /CharStrings get length 1 sub pn nl
  578. X
  579. X% check encoded chars
  580. X0 1 255 {
  581. X   dup en exch get 
  582. X   dup /.notdef ne { % C 77 ; WX 889 ; N M ; B 19 0 871 662 ;
  583. X      (C ) print                                % character number
  584. X      exch dup pn exch
  585. X      ( ; WX ) print                            % character width
  586. X      fn /Metrics known {
  587. X         dup fn /Metrics get exch get 
  588. X         dup type /arraytype eq {
  589. X            dup length 2 eq
  590. X            {1 get} {2 get} ifelse
  591. X         } if
  592. X      } {
  593. X         ( ) dup 0 4 index put stringwidth pop round cvi
  594. X      } ifelse
  595. X      pn
  596. X      ( ; N ) print                             % character name
  597. X      pn
  598. X      newpath 0 0 moveto
  599. X      ( ; B ) print                             % BoundingBox
  600. X      ( ) dup 0 4 -1 roll put
  601. X      true charpath flattenpath pathbbox printbb
  602. X      ( ;\n) print                              % finished!
  603. X   } {pop pop} ifelse
  604. X} for
  605. X
  606. X% get unencoded characters into MyEncoding array (problem if >256 unencoded)
  607. X/MyEncoding 256 array def
  608. X/Reverse 256 dict def
  609. XReverse begin
  610. X   en { % reverse encoding dictionary
  611. X      true def
  612. X   } forall
  613. Xend
  614. X
  615. X0 % start at beginning of MyEncoding
  616. Xfn /CharStrings get {
  617. X   pop % discard encrypted string
  618. X   dup Reverse exch known not % test if key is in normal encoding
  619. X   {
  620. X     MyEncoding 2 index 3 -1 roll put 1 add
  621. X   } {pop} ifelse
  622. X} forall
  623. X1 255 { % fill out with notdefs
  624. X   MyEncoding exch /.notdef put
  625. X} for
  626. X
  627. Xfn dup length dict begin
  628. X  {1 index /FID ne {def} {pop pop} ifelse} forall
  629. X  /Encoding MyEncoding def
  630. X  currentdict
  631. Xend /newfont exch definefont
  632. Xdup /fn exch def setfont
  633. X/en MyEncoding def
  634. X
  635. X% check encoded chars
  636. X0 1 255 {
  637. X   dup en exch get
  638. X   dup /.notdef ne { % C -1 ; WX 889 ; N M ; B 19 0 871 662 ;
  639. X      (C -1) print                                % character number
  640. X      ( ; WX ) print                            % character width
  641. X      fn /Metrics known {
  642. X         dup fn /Metrics get exch get 
  643. X         dup type /arraytype eq {
  644. X            dup length 2 eq
  645. X            {1 get} {2 get} ifelse
  646. X         } if
  647. X      } {
  648. X         ( ) dup 0 4 index put stringwidth pop round cvi
  649. X      } ifelse
  650. X      pn
  651. X      ( ; N ) print                             % character name
  652. X      pn
  653. X      newpath 0 0 moveto
  654. X      ( ; B ) print                             % BoundingBox
  655. X      ( ) dup 0 4 -1 roll put
  656. X      true charpath flattenpath pathbbox printbb
  657. X      ( ;\n) print                              % finished!
  658. X   } {pop pop exit} ifelse
  659. X} for
  660. X(EndCharMetrics\n)print
  661. Xflush
  662. XEOF
  663. END_OF_getafm
  664. if test 4706 -ne `wc -c <getafm`; then
  665.     echo shar: \"getafm\" unpacked with wrong size!
  666. fi
  667. chmod +x getafm
  668. # end of overwriting check
  669. fi
  670. if test -f psbook.1 -a "${1}" != "-c" ; then 
  671.   echo shar: Will not over-write existing file \"psbook.1\"
  672. else
  673. echo shar: Extracting \"psbook.1\" \(1066 characters\)
  674. sed "s/^X//" >psbook.1 <<'END_OF_psbook.1'
  675. X.TH PSBOOK 1
  676. X.SH NAME
  677. Xpsbook \- rearrange pages in PostScript file into signatures
  678. X.SH SYNOPSIS
  679. X.B psbook
  680. X[
  681. X.B \-q
  682. X] [
  683. X.B \-s\fIsignature\fR
  684. X] [
  685. X.I infile
  686. X[
  687. X.I outfile
  688. X] ]
  689. X.SH DESCRIPTION
  690. X.I Psbook
  691. Xrearranges pages from a PostScript document into ``signatures'' for
  692. Xprinting books or booklets, creating a new PostScript file. The
  693. Xinput PostScript file should follow the Adobe Document Structuring
  694. XConventions.
  695. X.PP
  696. XThe
  697. X.I \-s
  698. Xoption selects the size of signature which will be used. The signature size is
  699. Xthe number of sides which will be folded and bound together; the number given
  700. Xshould be a multiple of four. The default is to use one signature for the
  701. Xwhole file. Extra blank sides will be added if the file does not contain a
  702. Xmultiple of four pages.
  703. X.PP
  704. XPsbook normally prints the page numbers of the pages rearranged; the
  705. X.I \-q
  706. Xoption suppresses this.
  707. X.SH AUTHOR
  708. XAngus Duggan
  709. X.SH "SEE ALSO"
  710. Xpsselect(1), pstops(1)
  711. X.SH TRADEMARKS
  712. X.B PostScript
  713. Xis a trademark of Adobe Systems Incorporated.
  714. X.SH BUGS
  715. X.I Psbook
  716. Xcannot cope with documents longer than 5000 pages.
  717. END_OF_psbook.1
  718. if test 1066 -ne `wc -c <psbook.1`; then
  719.     echo shar: \"psbook.1\" unpacked with wrong size!
  720. fi
  721. # end of overwriting check
  722. fi
  723. if test -f psbook.c -a "${1}" != "-c" ; then 
  724.   echo shar: Will not over-write existing file \"psbook.c\"
  725. else
  726. echo shar: Extracting \"psbook.c\" \(1990 characters\)
  727. sed "s/^X//" >psbook.c <<'END_OF_psbook.c'
  728. X/* psbook.c
  729. X * AJCD 27/1/91
  730. X * rearrange pages in conforming PS file for printing in signatures
  731. X *
  732. X * Usage:
  733. X *       psbook [-q] [-s<signature>] [infile [outfile]]
  734. X */
  735. X
  736. X#include "psutil.h"
  737. X
  738. Xvoid usage()
  739. X{
  740. X   fprintf(stderr, "Usage: %s [-q] [-s<signature>] [infile [outfile]]\n",
  741. X       prog);
  742. X   fprintf(stderr, "       <signature> must be positive and divisible by 4\n");
  743. X   fflush(stderr);
  744. X   exit(1);
  745. X}
  746. X
  747. X
  748. Xmain(argc, argv)
  749. X     int argc;
  750. X     char *argv[];
  751. X{
  752. X   int signature = 0;
  753. X   int currentpg, maxpage;
  754. X
  755. X   infile = stdin;
  756. X   outfile = stdout;
  757. X   verbose = 1;
  758. X   for (prog = *argv++; --argc; argv++) {
  759. X      if (argv[0][0] == '-') {
  760. X     switch (argv[0][1]) {
  761. X     case 's':
  762. X        signature = atoi(*argv+2);
  763. X        if (signature < 1 || signature % 4) usage();
  764. X        break;
  765. X     case 'q':
  766. X        verbose = 0;
  767. X        break;
  768. X     default:
  769. X        usage();
  770. X     }
  771. X      } else if (infile == stdin) {
  772. X     if ((infile = fopen(*argv, "r")) == NULL) {
  773. X        fprintf(stderr, "%s: can't open input file %s\n", prog, *argv);
  774. X        fflush(stderr);
  775. X        exit(1);
  776. X     }
  777. X      } else if (outfile == stdout) {
  778. X     if ((outfile = fopen(*argv, "w")) == NULL) {
  779. X        fprintf(stderr, "%s: can't open output file %s\n", prog, *argv);
  780. X        fflush(stderr);
  781. X        exit(1);
  782. X     }
  783. X      } else usage();
  784. X   }
  785. X   if ((infile=seekable(infile))==NULL) {
  786. X      fprintf(stderr, "%s: can't seek input\n", prog);
  787. X      fflush(stderr);
  788. X      exit(1);
  789. X   }
  790. X   scanpages();
  791. X
  792. X   maxpage = pages+(4-pages%4)%4;
  793. X
  794. X   if (!signature)
  795. X      signature = maxpage;
  796. X
  797. X   /* rearrange pages */
  798. X   writeheader(maxpage);
  799. X   writeprolog();
  800. X   for (currentpg = 0; currentpg < maxpage; currentpg++) {
  801. X      int actualpg = currentpg - currentpg%signature;
  802. X      switch(currentpg%4) {
  803. X      case 0:
  804. X      case 3:
  805. X     actualpg += signature-1-(currentpg%signature)/2;
  806. X     break;
  807. X      case 1:
  808. X      case 2:
  809. X     actualpg += (currentpg%signature)/2;
  810. X     break;
  811. X      }
  812. X      if (actualpg < pages)
  813. X     writepage(actualpg);
  814. X      else
  815. X     writeemptypage();
  816. X   }
  817. X   writetrailer();
  818. X
  819. X   exit(0);
  820. X}
  821. END_OF_psbook.c
  822. if test 1990 -ne `wc -c <psbook.c`; then
  823.     echo shar: \"psbook.c\" unpacked with wrong size!
  824. fi
  825. # end of overwriting check
  826. fi
  827. if test -f psnup -a "${1}" != "-c" ; then 
  828.   echo shar: Will not over-write existing file \"psnup\"
  829. else
  830. echo shar: Extracting \"psnup\" \(2113 characters\)
  831. sed "s/^X//" >psnup <<'END_OF_psnup'
  832. X#!/bin/sh
  833. X# psnup: put multiple pages onto one physical sheet of paper.
  834. X# usage:
  835. X#       psnup [-w<dim>] [-h<dim>] [-l] [-2|-4|-8|-9] [file...]
  836. X#               -w<dim> sets the paper width
  837. X#               -h<dim> sets the paper height
  838. X#               -l      is used if the pages are in landscape orientation
  839. X
  840. Xio= landscape=0 nup=1 width=-w21cm height=-h29.7cm
  841. X
  842. Xwhile test $# != 0
  843. Xdo      case "$1" in
  844. X        -w*)    width=$1 ;;
  845. X        -h*)    height=$1 ;;
  846. X        -l)     landscape=1 ;;
  847. X        -2)     nup=2 ;;
  848. X        -4)     nup=4 ;;
  849. X        -8)     nup=8 ;;
  850. X        -9)     nup=9 ;;
  851. X        *)      io="$io $1"
  852. X        esac
  853. X        shift
  854. Xdone
  855. X
  856. Xscale= offset=
  857. Xcase "$nup" in
  858. X2)      scale=@0.707
  859. X        if [ $landscape = 0 ]
  860. X        then offset="(1w,0) (1w,0.5h)"
  861. X        else offset="(0,0.5h) (0,0)"
  862. X        fi
  863. X        landscape=`expr 1 - $landscape` ;;
  864. X4)      scale=@0.5
  865. X        if [ $landscape = 0 ]
  866. X        then offset="(0,0.5h) (0.5w,0.5h) (0,0) (0.5w,0)"
  867. X        else offset="(0.5w,0) (0.5w,0.5h) (1w,0) (1w,0.5h)"
  868. X        fi ;;
  869. X8)      scale=@0.3536
  870. X        if [ $landscape = 0 ]
  871. X        then offset="(0.5w,0) (0.5w,0.25h) (0.5w,0.5h) (0.5w,0.75h)\
  872. X                     (1w,0) (1w,0.25h) (1w,0.5h) (1w,0.75h)"
  873. X        else offset="(0,0.75h) (0.5w,0.75h) (0,0.5h) (0.5w,0.5h)\
  874. X                     (0,0.25h) (0.5w,0.25h) (0,0) (0.5w,0)"
  875. X        fi
  876. X        landscape=`expr 1 - $landscape` ;;
  877. X9)      scale=@0.3333
  878. X        if [ $landscape = 0 ]
  879. X        then offset="(0,0.666h) (0.333w,0.666h) (0.666w,0.666h)\
  880. X                     (0,0.333h) (0.333w,0.333h) (0.666w,0.333h)\
  881. X                     (0,0) (0.333w,0) (0.666w,0)"
  882. X        else offset="(0.333w,0) (0.333w,0.333h) (0.333w,0.666h)\
  883. X                     (0.666w,0) (0.666w,0.333h) (0.666w,0.666h)\
  884. X                     (1w,0) (1w,0.333h) (1w,0.666h)"
  885. X        fi ;;
  886. Xesac
  887. X
  888. Xif [ $landscape = 0 ]
  889. Xthen rotate=
  890. Xelse rotate=L
  891. Xfi
  892. X
  893. Xoptions= sep= page=0
  894. X
  895. Xset -- ${offset:-""}
  896. Xwhile [ $page -lt $nup ]
  897. Xdo      options="$options${options:++}$page$rotate$scale$1"
  898. X        page=`expr $page + 1`
  899. X        shift
  900. Xdone
  901. X
  902. Xpstops $width $height "$nup:$options" $io
  903. END_OF_psnup
  904. if test 2113 -ne `wc -c <psnup`; then
  905.     echo shar: \"psnup\" unpacked with wrong size!
  906. fi
  907. chmod +x psnup
  908. # end of overwriting check
  909. fi
  910. if test -f psnup.1 -a "${1}" != "-c" ; then 
  911.   echo shar: Will not over-write existing file \"psnup.1\"
  912. else
  913. echo shar: Extracting \"psnup.1\" \(2146 characters\)
  914. sed "s/^X//" >psnup.1 <<'END_OF_psnup.1'
  915. X.TH PSNUP 1
  916. X.SH NAME
  917. Xpsnup \- select pages from a PostScript file
  918. X.SH SYNOPSIS
  919. X.B pstops
  920. X[
  921. X.B \-q
  922. X]
  923. X[
  924. X.B \-w\fIwidth\fR
  925. X]
  926. X[
  927. X.B \-h\fIheight\fR
  928. X]
  929. X[
  930. X.B \-l
  931. X]
  932. X[
  933. X.B \-2 | \-4 | \-8 | \-h
  934. X]
  935. X[
  936. X.I infile
  937. X] ]
  938. X.SH DESCRIPTION
  939. X.I Psnup
  940. Xis a script making the use of 
  941. X.I pstops 
  942. Xeasier.
  943. XIt sets up standard width and height parameters and 
  944. X.I Pstops
  945. Xrearranges pages from a PostScript document, creating a new PostScript file.
  946. XThe input PostScript file should follow the Adobe Document Structuring
  947. XConventions.
  948. X.I Pstops
  949. Xcan be used to perform a large number of arbitrary re-arrangements of
  950. XDocuments, including arranging for printing 2-up, 4-up, booklets, reversing,
  951. Xselecting front or back sides of documents, scaling, etc.
  952. X.PP
  953. XThe
  954. X.I \-w
  955. Xoption gives the width, the default is (8.25in),
  956. X.I \-h
  957. Xoption gives the height, the default is (11.75in), 
  958. Xand are normally specified in
  959. X.B "cm"
  960. Xor
  961. X.B "in"
  962. Xto convert 
  963. XPostScript's points (1/72 of an inch)
  964. Xto centimeters or inches
  965. X.PP
  966. XThe
  967. X.I \-b
  968. Xoption prevents any
  969. X.B bind
  970. Xoperators in the PostScript prolog from binding. This may be needed in cases
  971. Xwhere complex multi-page re-arrangements are being done.
  972. X.PP
  973. XPstops normally prints the page numbers of the pages re-arranged; the
  974. X.I \-q
  975. Xoption suppresses this.
  976. X.SH EXAMPLES
  977. XThe potential use of this utility is varied but one particular 
  978. Xuse is in conjunction with 
  979. X.I psbook(1).
  980. XFor example, using psroff to create a PostScript document and lpr as 
  981. Xthe 
  982. X.SM UNIX 
  983. Xprint spooler a typical command line might look like this: 
  984. X.sp
  985. Xpsroff -ms \fIfile\fP | psbook | psnup -2 | lpr
  986. X.sp
  987. XWhere file is a 4 page document this command will result in a 
  988. Xtwo page document printing two pages of \fIfile\fP per page and
  989. Xrearranges the page order to match the input pages 4 and 1 
  990. Xon the first output page and
  991. Xpages 2 then 3 of the input document 
  992. Xon the second output page.
  993. X.SH AUTHOR
  994. XAngus Duggan
  995. X.br
  996. XBrian Colfer, University of California, San Francisco
  997. X.br
  998. Xbrianc@labmed.ucsf.edu
  999. X.SH "SEE ALSO"
  1000. Xpsbook(1), pstops(1), psroff(1)
  1001. X.SH TRADEMARKS
  1002. X.B PostScript
  1003. Xis a trademark of Adobe Systems Incorporated.
  1004. X.SH BUGS
  1005. X.I Pstops
  1006. Xcannot cope with documents longer than 5000 pages.
  1007. END_OF_psnup.1
  1008. if test 2146 -ne `wc -c <psnup.1`; then
  1009.     echo shar: \"psnup.1\" unpacked with wrong size!
  1010. fi
  1011. # end of overwriting check
  1012. fi
  1013. if test -f psselect.1 -a "${1}" != "-c" ; then 
  1014.   echo shar: Will not over-write existing file \"psselect.1\"
  1015. else
  1016. echo shar: Extracting \"psselect.1\" \(1509 characters\)
  1017. sed "s/^X//" >psselect.1 <<'END_OF_psselect.1'
  1018. X.TH PSSELECT 1
  1019. X.SH NAME
  1020. Xpsselect \- select pages from a PostScript file
  1021. X.SH SYNOPSIS
  1022. X.B psselect
  1023. X[
  1024. X.B \-q
  1025. X] [
  1026. X.B \-e
  1027. X] [
  1028. X.B \-o
  1029. X] [
  1030. X.B \-r
  1031. X] [
  1032. X.B \-p\fIpages\fR
  1033. X] [
  1034. X.I infile
  1035. X[
  1036. X.I outfile
  1037. X] ]
  1038. X.SH DESCRIPTION
  1039. X.I Psselect
  1040. Xselects pages from a PostScript document, creating a new PostScript file. The
  1041. Xinput PostScript file should follow the Adobe Document Structuring
  1042. XConventions.
  1043. X.PP
  1044. XThe 
  1045. X.I \-e
  1046. Xoption selects all of the even pages; it may be used in conjunction with the
  1047. Xother page selection options.
  1048. X.PP
  1049. XThe 
  1050. X.I \-o
  1051. Xoption selects all of the odd pages; it may be used in conjunction with the
  1052. Xother page selection options.
  1053. X.PP
  1054. XThe 
  1055. X.I \-p\fIpages\fR
  1056. Xoption specifies the pages which are to be selected.
  1057. X.I Pages
  1058. Xis a comma separated list of page ranges, each of which may be a page number,
  1059. Xor a page range of the form \fIfirst\fR-\fIlast\fR. If \fIfirst\fR is omitted,
  1060. Xthe
  1061. Xfirst page is assumed, and if \fIlast\fR is omitted, the last page is assumed.
  1062. X.PP
  1063. XThe 
  1064. X.I \-r
  1065. Xoption causes
  1066. X.I psselect
  1067. Xto output the selected pages in reverse order.
  1068. X.PP
  1069. XPsselect normally prints the page numbers of the pages rearranged; the
  1070. X.I \-q
  1071. Xoption suppresses this.
  1072. X.SH NOTES
  1073. X.I Psselect
  1074. Xselects pages in the order that they appear in the file, starting from one. The
  1075. Xactual page number in the document may be different.
  1076. X.SH AUTHOR
  1077. XAngus Duggan
  1078. X.SH "SEE ALSO"
  1079. Xpsbook(1), pstops(1)
  1080. X.SH TRADEMARKS
  1081. X.B PostScript
  1082. Xis a trademark of Adobe Systems Incorporated.
  1083. X.SH BUGS
  1084. X.I Psselect
  1085. Xcannot cope with documents longer than 5000 pages.
  1086. END_OF_psselect.1
  1087. if test 1509 -ne `wc -c <psselect.1`; then
  1088.     echo shar: \"psselect.1\" unpacked with wrong size!
  1089. fi
  1090. # end of overwriting check
  1091. fi
  1092. if test -f psselect.c -a "${1}" != "-c" ; then 
  1093.   echo shar: Will not over-write existing file \"psselect.c\"
  1094. else
  1095. echo shar: Extracting \"psselect.c\" \(4621 characters\)
  1096. sed "s/^X//" >psselect.c <<'END_OF_psselect.c'
  1097. X/* psselect.c
  1098. X * AJCD 27/1/91
  1099. X * rearrange pages in conforming PS file for printing in signatures
  1100. X *
  1101. X * Usage:
  1102. X *       psselect [-q] [-e] [-o] [-r] [-p<pages>] [infile [outfile]]
  1103. X */
  1104. X
  1105. X#include "psutil.h"
  1106. X
  1107. Xvoid usage()
  1108. X{
  1109. X   fprintf(stderr,
  1110. X       "Usage: %s [-q] [-e] [-o] [-r] [-p<pages>] [infile [outfile]]\n",
  1111. X       prog);
  1112. X   fflush(stderr);
  1113. X   exit(1);
  1114. X}
  1115. X
  1116. Xstruct pgrange {
  1117. X   int first, last;
  1118. X   struct pgrange *next;
  1119. X};
  1120. X
  1121. Xtypedef struct pgrange range;
  1122. X
  1123. Xrange * makerange(beg, end, next)
  1124. X     int beg, end;
  1125. X     range *next;
  1126. X{
  1127. X   range *new;
  1128. X   if ((new = (range *)malloc(sizeof(range))) == NULL) {
  1129. X      fprintf(stderr, "%s: out of memory\n", prog);
  1130. X      fflush(stderr);
  1131. X      exit(1);
  1132. X   }
  1133. X   new->first = beg;
  1134. X   new->last = end;
  1135. X   new->next = next;
  1136. X   return (new);
  1137. X}
  1138. X
  1139. Xrange * mergerange(beg, end, curr)
  1140. X     int beg, end;
  1141. X     range *curr;
  1142. X{
  1143. X   if (curr) {
  1144. X      range *this, *prev;
  1145. X      for (this=prev=curr; this; prev=this, this=this->next) {
  1146. X     int lo = (beg < curr->first) ? -1 : (beg > curr->last) ? 1 : 0;
  1147. X     int hi = (end < curr->first) ? -1 : (end > curr->last) ? 1 : 0;
  1148. X     if (hi < 0)
  1149. X        return (makerange(beg, end, curr));
  1150. X     else if (lo <= 0) { /* beginning of range */
  1151. X        if (lo < 0)
  1152. X           this->first = beg;
  1153. X        if (hi > 0) {
  1154. X           while (this->next && this->next->first <= end) {
  1155. X          range *eaten = this->next;
  1156. X          this->next = eaten->next;
  1157. X          if (eaten->last > end)
  1158. X             end = eaten->last;
  1159. X          free(eaten);
  1160. X           }
  1161. X           this->last = end;
  1162. X        }  /* else range included; no change */
  1163. X        return (curr);
  1164. X     }
  1165. X      }
  1166. X      prev->next = makerange(beg, end, NULL);
  1167. X      return (curr);
  1168. X   } else return (makerange(beg, end, NULL));
  1169. X}
  1170. X
  1171. X
  1172. Xrange * addrange(str, rp)
  1173. X     char *str;
  1174. X     range *rp;
  1175. X{
  1176. X   int first=0;
  1177. X   if (isdigit(*str)) {
  1178. X      first = atoi(str);
  1179. X      while (isdigit(*str)) str++;
  1180. X   }
  1181. X   switch (*str) {
  1182. X   case '\0':
  1183. X      if (first)
  1184. X     return (mergerange(first, first, rp));
  1185. X      break;
  1186. X   case ',':
  1187. X      if (first)
  1188. X     return (addrange(str+1, mergerange(first, first, rp)));
  1189. X      break;
  1190. X   case '-':
  1191. X   case ':':
  1192. X      str++;
  1193. X      if (isdigit(*str)) {
  1194. X     int last = atoi(str);
  1195. X     while (isdigit(*str)) str++;
  1196. X     if (!first)
  1197. X        first = 1;
  1198. X     if (last >= first) 
  1199. X        switch (*str) {
  1200. X        case '\0':
  1201. X           return (mergerange(first, last, rp));
  1202. X        case ',':
  1203. X           return (addrange(str+1, mergerange(first, last, rp)));
  1204. X        }
  1205. X      } else if (*str == '\0')
  1206. X     return (mergerange(first, MAXPAGES, rp));
  1207. X   }
  1208. X   fprintf(stderr, "%s: invalid page range\n", prog);
  1209. X   fflush(stderr);
  1210. X   exit(1);
  1211. X}
  1212. X
  1213. X
  1214. Xint selectpage(page, even, odd, rp)
  1215. X     int page, even, odd;
  1216. X     range *rp;
  1217. X{
  1218. X   if (page&1) {
  1219. X      if (odd) return (1);
  1220. X   } else {
  1221. X      if (even) return (1);
  1222. X   }
  1223. X   while (rp) {
  1224. X      if (page >= rp->first) {
  1225. X     if (page <= rp->last)
  1226. X        return (1);
  1227. X      } else return (0);
  1228. X      rp = rp->next;
  1229. X   }
  1230. X   return (0);
  1231. X}
  1232. X
  1233. X
  1234. Xmain(argc, argv)
  1235. X     int argc;
  1236. X     char *argv[];
  1237. X{
  1238. X   int currentpg, maxpage = 0;
  1239. X   int even = 0, odd = 0, all = 1, reverse = 0;
  1240. X   range *pagerange = NULL;
  1241. X
  1242. X   infile = stdin;
  1243. X   outfile = stdout;
  1244. X   verbose = 1;
  1245. X   for (prog = *argv++; --argc; argv++) {
  1246. X      if (argv[0][0] == '-') {
  1247. X     switch (argv[0][1]) {
  1248. X     case 'e':
  1249. X        even = 1; all = 0;
  1250. X        break;
  1251. X     case 'o':
  1252. X        odd = 1; all = 0; 
  1253. X        break;
  1254. X     case 'r':
  1255. X        reverse = 1;
  1256. X        break;
  1257. X     case 'p':
  1258. X        pagerange = addrange(*argv+2, pagerange); all = 0;
  1259. X        break;
  1260. X     case 'q':
  1261. X        verbose = 0;
  1262. X        break;
  1263. X     default:
  1264. X        usage();
  1265. X     }
  1266. X      } else if (infile == stdin) {
  1267. X     if ((infile = fopen(*argv, "r")) == NULL) {
  1268. X        fprintf(stderr, "%s: can't open input file %s\n", prog, *argv);
  1269. X        fflush(stderr);
  1270. X        exit(1);
  1271. X     }
  1272. X      } else if (outfile == stdout) {
  1273. X     if ((outfile = fopen(*argv, "w")) == NULL) {
  1274. X        fprintf(stderr, "%s: can't open output file %s\n", prog, *argv);
  1275. X        fflush(stderr);
  1276. X        exit(1);
  1277. X     }
  1278. X      } else usage();
  1279. X   }
  1280. X   if ((infile=seekable(infile))==NULL) {
  1281. X      fprintf(stderr, "%s: can't seek input\n", prog);
  1282. X      fflush(stderr);
  1283. X      exit(1);
  1284. X   }
  1285. X   scanpages();
  1286. X
  1287. X   for (currentpg = 1; currentpg <= pages; currentpg++)
  1288. X      if (selectpage(currentpg, even || all, odd || all, pagerange))
  1289. X     maxpage++;
  1290. X
  1291. X   /* select pages */
  1292. X   writeheader(maxpage);
  1293. X   writeprolog();
  1294. X   if (reverse) {
  1295. X      for (currentpg = pages; currentpg > 0; currentpg--)
  1296. X     if (selectpage(currentpg, even || all, odd || all, pagerange))
  1297. X        writepage(currentpg-1);
  1298. X   } else {
  1299. X      for (currentpg = 1; currentpg <= pages; currentpg++)
  1300. X     if (selectpage(currentpg, even || all, odd || all, pagerange))
  1301. X        writepage(currentpg-1);
  1302. X   }
  1303. X   writetrailer();
  1304. X
  1305. X   exit(0);
  1306. X}
  1307. END_OF_psselect.c
  1308. if test 4621 -ne `wc -c <psselect.c`; then
  1309.     echo shar: \"psselect.c\" unpacked with wrong size!
  1310. fi
  1311. # end of overwriting check
  1312. fi
  1313. if test -f pstops.1 -a "${1}" != "-c" ; then 
  1314.   echo shar: Will not over-write existing file \"pstops.1\"
  1315. else
  1316. echo shar: Extracting \"pstops.1\" \(3227 characters\)
  1317. sed "s/^X//" >pstops.1 <<'END_OF_pstops.1'
  1318. X.TH PSTOPS 1
  1319. X.SH NAME
  1320. Xpstops \- select pages from a PostScript file
  1321. X.SH SYNOPSIS
  1322. X.B pstops
  1323. X[
  1324. X.B \-q
  1325. X]
  1326. X[
  1327. X.B \-b
  1328. X]
  1329. X[
  1330. X.B \-w\fIwidth\fR
  1331. X]
  1332. X[
  1333. X.B \-h\fIheight\fR
  1334. X]
  1335. X.I pagespecs
  1336. X[
  1337. X.I infile
  1338. X[
  1339. X.I outfile
  1340. X] ]
  1341. X.SH DESCRIPTION
  1342. X.I Pstops
  1343. Xrearranges pages from a PostScript document, creating a new PostScript file.
  1344. XThe input PostScript file should follow the Adobe Document Structuring
  1345. XConventions.
  1346. X.I Pstops
  1347. Xcan be used to perform a large number of arbitrary re-arrangements of
  1348. XDocuments, including arranging for printing 2-up, 4-up, booklets, reversing,
  1349. Xselecting front or back sides of documents, scaling, etc.
  1350. X.PP
  1351. X.I pagespecs
  1352. Xfollow the syntax:
  1353. X.RS
  1354. X.TP 12
  1355. X.I pagespecs
  1356. X.I = [modulo:]specs
  1357. X.TP
  1358. X.I specs
  1359. X.I = spec[+specs][,specs]
  1360. X.TP
  1361. X.I spec
  1362. X.I = [-]pageno[@scale][L][R][U][(xoff,yoff)]
  1363. X.RE
  1364. X.sp
  1365. X.I modulo
  1366. Xis the number of pages in each block. The value of
  1367. X.I modulo
  1368. Xshould be greater than 0; the default value is 1.
  1369. X.I specs
  1370. Xare the page specifications for the pages in each block. The value of the
  1371. X.I pageno
  1372. Xin each
  1373. X.I spec
  1374. Xshould be between 0 (for the first page in the block) and \fImodulo\fR-1
  1375. X(for the last page in each block) inclusive.
  1376. XThe optional dimensions
  1377. X.I xoff
  1378. Xand
  1379. X.I yoff
  1380. Xshift the page by the specified (positive) amount.
  1381. X.I xoff
  1382. Xand
  1383. X.I yoff
  1384. Xare in PostScript's points, but may be followed by the units
  1385. X.B "cm"
  1386. Xor
  1387. X.B "in"
  1388. Xto convert to centimetres or inches, or the flag
  1389. X.B "w"
  1390. Xor
  1391. X.B "h"
  1392. Xto specify as a multiple of the width or height.
  1393. XThe optional parameters \fIL\fR, \fIR\fR, and \fIU\fR rotate the page left,
  1394. Xright, or upside-down.
  1395. XThe optional
  1396. X.I scale
  1397. Xparameter scales the page by the fraction specified.
  1398. XIf the optional minus sign is specified, the page is relative to the end of
  1399. Xthe document, instead of the start.
  1400. X
  1401. XIf page \fIspec\fRs are separated by
  1402. X.B \+
  1403. Xthe pages will be merged into one page; if they are separated by
  1404. X.B \,
  1405. Xthey will be on separate pages.
  1406. XIf there is only one page specification, with
  1407. X.I pageno
  1408. Xzero, the \fIpageno\fR may be omitted.
  1409. X.PP
  1410. XThe
  1411. X.I \-w
  1412. Xoption gives the width which is used by the
  1413. X.B "w"
  1414. Xdimension specifier, and the
  1415. X.I \-h
  1416. Xoption gives the height which is used by the
  1417. X.B "h"
  1418. Xdimension specifier. These dimensions are also used (after scaling) to set the
  1419. Xclipping path for each page.
  1420. X.PP
  1421. XThe
  1422. X.I \-b
  1423. Xoption prevents any
  1424. X.B bind
  1425. Xoperators in the PostScript prolog from binding. This may be needed in cases
  1426. Xwhere complex multi-page re-arrangements are being done.
  1427. X.PP
  1428. XPstops normally prints the page numbers of the pages re-arranged; the
  1429. X.I \-q
  1430. Xoption suppresses this.
  1431. X.SH EXAMPLES
  1432. XThis section contains some sample re-arrangements. To put two pages on one
  1433. Xsheet (of A4 paper), the pagespec to use is:
  1434. X.sp
  1435. X.ce
  1436. X2:0L@0.7(21cm,0)+1L@0.7(21cm,14.85cm)
  1437. X.sp
  1438. XTo select all of the odd pages in reverse order, use:
  1439. X.sp
  1440. X.ce
  1441. X2:-0
  1442. X.sp
  1443. XTo re-arrange pages for printing 2-up booklets, use
  1444. X.sp
  1445. X.ce
  1446. X4:-3L@0.7(21cm,0)+0L@0.7(21cm,14.85cm)
  1447. X.sp
  1448. Xfor the front sides, and
  1449. X.sp
  1450. X.ce
  1451. X4:1L@0.7(21cm,0)+-2L@0.7(21cm,14.85cm)
  1452. X.sp
  1453. Xfor the reverse sides (or join them with a comma for duplex printing).
  1454. X.SH AUTHOR
  1455. XAngus Duggan
  1456. X.SH "SEE ALSO"
  1457. Xpsbook(1), psselect(1)
  1458. X.SH TRADEMARKS
  1459. X.B PostScript
  1460. Xis a trademark of Adobe Systems Incorporated.
  1461. X.SH BUGS
  1462. X.I Pstops
  1463. Xcannot cope with documents longer than 5000 pages.
  1464. END_OF_pstops.1
  1465. if test 3227 -ne `wc -c <pstops.1`; then
  1466.     echo shar: \"pstops.1\" unpacked with wrong size!
  1467. fi
  1468. # end of overwriting check
  1469. fi
  1470. if test -f pstops.c -a "${1}" != "-c" ; then 
  1471.   echo shar: Will not over-write existing file \"pstops.c\"
  1472. else
  1473. echo shar: Extracting \"pstops.c\" \(9273 characters\)
  1474. sed "s/^X//" >pstops.c <<'END_OF_pstops.c'
  1475. X/* pstops.c
  1476. X * AJCD 27/1/91
  1477. X * rearrange pages in conforming PS file for printing in signatures
  1478. X *
  1479. X * Usage:
  1480. X *       pstops [-q] [-b] [-w<dim>] [-h<dim>] <pagespecs> [infile [outfile]]
  1481. X */
  1482. X
  1483. X#include "psutil.h"
  1484. X
  1485. Xvoid usage()
  1486. X{
  1487. X   fprintf(stderr, "Usage: %s [-q] [-b] [-w<dim>] [-h<dim] <pagespecs> [infile [outfile]]\n",
  1488. X       prog);
  1489. X   fflush(stderr);
  1490. X   exit(1);
  1491. X}
  1492. X
  1493. Xvoid specusage()
  1494. X{
  1495. X   fprintf(stderr, "%s: page specification error:\n", prog);
  1496. X   fprintf(stderr, "  <pagespecs> = [modulo:]<spec>\n");
  1497. X   fprintf(stderr, "  <spec>      = [-]pageno[@scale][L|R|U][(xoff,yoff)][,spec|+spec]\n");
  1498. X   fprintf(stderr, "                modulo>=1, 0<=pageno<modulo\n");
  1499. X   fflush(stderr);
  1500. X   exit(1);
  1501. X}
  1502. X
  1503. Xstatic int modulo = 1;
  1504. Xstatic int pagesperspec = 1;
  1505. Xstatic double width = -1.0;
  1506. Xstatic double height = -1.0;
  1507. X
  1508. X/* pagespec flags */
  1509. X#define ADD_NEXT (0x01)
  1510. X#define ROTATE   (0x02)
  1511. X#define SCALE    (0x04)
  1512. X#define OFFSET   (0x08)
  1513. X#define GSAVE    (ROTATE|SCALE|OFFSET)
  1514. X
  1515. Xstruct pagespec {
  1516. X   int reversed, pageno, flags, rotate;
  1517. X   double xoff, yoff, scale;
  1518. X   struct pagespec *next;
  1519. X};
  1520. X
  1521. Xstruct pagespec *newspec()
  1522. X{
  1523. X   struct pagespec *temp = (struct pagespec *)malloc(sizeof(struct pagespec));
  1524. X   temp->reversed = temp->pageno = temp->flags = temp->rotate = 0;
  1525. X   temp->scale = 1.0;
  1526. X   temp->xoff = temp->yoff = 0.0;
  1527. X   temp->next = NULL;
  1528. X   return (temp);
  1529. X}
  1530. X
  1531. Xint parseint(sp)
  1532. X     char **sp;
  1533. X{
  1534. X   char *s;
  1535. X   int n = 0;
  1536. X
  1537. X   for (s = *sp; isdigit(*s); s++)
  1538. X      n = n*10 + (*s-'0');
  1539. X   if (*sp == s) specusage();
  1540. X   *sp = s;
  1541. X   return (n);
  1542. X}
  1543. X
  1544. Xdouble parsedouble(sp)
  1545. X     char **sp;
  1546. X{
  1547. X   int n = parseint(sp);
  1548. X   char *s = *sp;
  1549. X   int d = 0, frac = 1;
  1550. X
  1551. X   if (*s == '.') {
  1552. X      *sp = ++s;
  1553. X      for (; isdigit(*s); s++) {
  1554. X     d = d*10 + (*s-'0');
  1555. X     frac *= 10;
  1556. X      }
  1557. X      if (*sp == s) specusage();
  1558. X   }
  1559. X   *sp = s;
  1560. X   return ((double)n+(double)d/frac);
  1561. X}
  1562. X
  1563. Xdouble parsedimen(sp)
  1564. X     char **sp;
  1565. X{
  1566. X   double num = parsedouble(sp);
  1567. X   char *s = *sp;
  1568. X
  1569. X   if (strncmp(s, "pt", 2) == 0) {
  1570. X      s += 2;
  1571. X   } else if (strncmp(s, "in", 2) == 0) {
  1572. X      num *= 72.0;
  1573. X      s += 2;
  1574. X   } else if (strncmp(s, "cm", 2) == 0) {
  1575. X      num *= 28.346456692913385211;
  1576. X      s += 2;
  1577. X   } else if (*s == 'w') {
  1578. X      if (width < 0.0) {
  1579. X     fprintf(stderr, "%s: width not initialised\n", prog);
  1580. X     fflush(stderr);
  1581. X     exit(1);
  1582. X      }
  1583. X      num *= width;
  1584. X      s++;
  1585. X   } else if (*s == 'h') {
  1586. X      if (height < 0.0) {
  1587. X     fprintf(stderr, "%s: height not initialised\n", prog);
  1588. X     fflush(stderr);
  1589. X     exit(1);
  1590. X      }
  1591. X      num *= height;
  1592. X      s++;
  1593. X   }
  1594. X   *sp = s;
  1595. X   return (num);
  1596. X}
  1597. X
  1598. Xstruct pagespec *parsespecs(str)
  1599. X     char *str;
  1600. X{
  1601. X   char *t;
  1602. X   struct pagespec *head, *tail;
  1603. X   int other = 0;
  1604. X   int num = -1;
  1605. X
  1606. X   head = tail = newspec();
  1607. X   while (*str) {
  1608. X      if (isdigit(*str)) {
  1609. X     num = parseint(&str);
  1610. X      } else {
  1611. X     switch (*str++) {
  1612. X     case ':':
  1613. X        if (other || head != tail || num < 1) specusage();
  1614. X        modulo = num;
  1615. X        num = -1;
  1616. X        break;
  1617. X     case '-':
  1618. X        tail->reversed = !tail->reversed;
  1619. X        break;
  1620. X     case '@':
  1621. X        if (num < 0) specusage();
  1622. X        tail->scale *= parsedouble(&str);
  1623. X        tail->flags |= SCALE;
  1624. X        break;
  1625. X     case 'l': case 'L':
  1626. X        tail->rotate += 90;
  1627. X        tail->flags |= ROTATE;
  1628. X        break;
  1629. X     case 'r': case 'R':
  1630. X        tail->rotate -= 90;
  1631. X        tail->flags |= ROTATE;
  1632. X        break;
  1633. X     case 'u': case 'U':
  1634. X        tail->rotate += 180;
  1635. X        tail->flags |= ROTATE;
  1636. X        break;
  1637. X     case '(':
  1638. X        tail->xoff += parsedimen(&str);
  1639. X        if (*str++ != ',') specusage();
  1640. X        tail->yoff += parsedimen(&str);
  1641. X        if (*str++ != ')') specusage();
  1642. X        tail->flags |= OFFSET;
  1643. X        break;
  1644. X     case '+':
  1645. X        tail->flags |= ADD_NEXT;
  1646. X     case ',':
  1647. X        if (num < 0 || num >= modulo) specusage();
  1648. X        if ((tail->flags & ADD_NEXT) == 0)
  1649. X           pagesperspec++;
  1650. X        tail->pageno = num;
  1651. X        tail->next = newspec();
  1652. X        tail = tail->next;
  1653. X        num = -1;
  1654. X        break;
  1655. X     default:
  1656. X        specusage();
  1657. X     }
  1658. X     other = 1;
  1659. X      }
  1660. X   }
  1661. X   if (num >= modulo)
  1662. X      specusage();
  1663. X   else if (num >= 0)
  1664. X      tail->pageno = num;
  1665. X   return (head);
  1666. X}
  1667. X
  1668. Xdouble singledimen(str)
  1669. X     char *str;
  1670. X{
  1671. X   double num = parsedimen(&str);
  1672. X   if (*str) usage();
  1673. X   return (num);
  1674. X}
  1675. X
  1676. X
  1677. Xmain(argc, argv)
  1678. X     int argc;
  1679. X     char *argv[];
  1680. X{
  1681. X   int thispg, maxpage;
  1682. X   int pageindex = 0;
  1683. X   struct pagespec *specs = NULL;
  1684. X   int nobinding = 0;
  1685. X
  1686. X   infile = stdin;
  1687. X   outfile = stdout;
  1688. X   verbose = 1;
  1689. X   for (prog = *argv++; --argc; argv++) {
  1690. X      if (argv[0][0] == '-') {
  1691. X     switch (argv[0][1]) {
  1692. X     case 'q':
  1693. X        verbose = 0;
  1694. X        break;
  1695. X     case 'b':
  1696. X        nobinding = 1;
  1697. X        break;
  1698. X     case 'w':
  1699. X        width = singledimen(*argv+2);
  1700. X        break;
  1701. X     case 'h':
  1702. X        height = singledimen(*argv+2);
  1703. X        break;
  1704. X     default:
  1705. X        if (specs == NULL)
  1706. X           specs = parsespecs(*argv);
  1707. X        else
  1708. X           usage();
  1709. X     }
  1710. X      } else if (specs == NULL)
  1711. X     specs = parsespecs(*argv);
  1712. X      else if (infile == stdin) {
  1713. X     if ((infile = fopen(*argv, "r")) == NULL) {
  1714. X        fprintf(stderr, "%s: can't open input file %s\n", prog, *argv);
  1715. X        fflush(stderr);
  1716. X        exit(1);
  1717. X     }
  1718. X      } else if (outfile == stdout) {
  1719. X     if ((outfile = fopen(*argv, "w")) == NULL) {
  1720. X        fprintf(stderr, "%s: can't open output file %s\n", prog, *argv);
  1721. X        fflush(stderr);
  1722. X        exit(1);
  1723. X     }
  1724. X      } else usage();
  1725. X   }
  1726. X   if (specs == NULL)
  1727. X      usage();
  1728. X   if ((infile=seekable(infile))==NULL) {
  1729. X      fprintf(stderr, "%s: can't seek input\n", prog);
  1730. X      fflush(stderr);
  1731. X      exit(1);
  1732. X   }
  1733. X   scanpages();
  1734. X
  1735. X   maxpage = ((pages+modulo-1)/modulo)*modulo;
  1736. X
  1737. X   /* rearrange pages: doesn't cope properly with:
  1738. X    * initmatrix, initgraphics, defaultmatrix, grestoreall, initclip */
  1739. X   writeheader((maxpage/modulo)*pagesperspec);
  1740. X   writestring("%%BeginProcSet: pstops 1 0\n");
  1741. X   writestring("[/showpage/erasepage/copypage]{dup where{pop dup load\n");
  1742. X   writestring(" type/operatortype eq{1 array cvx dup 0 3 index cvx put\n");
  1743. X   writestring(" bind def}{pop}ifelse}{pop}ifelse}forall\n");
  1744. X   writestring("[/letter/legal/executivepage/a4/a4small/b5/com10envelope\n");
  1745. X   writestring(" /monarchenvelope/c5envelope/dlenvelope/lettersmall/note\n");
  1746. X   writestring(" /folio/quarto/a5]{dup where{exch{}put}{pop}ifelse}forall\n");
  1747. X   writestring("/lcvx{dup load dup type dup/operatortype eq{pop exch pop}\n");
  1748. X   writestring(" {/arraytype eq{dup xcheck{exch pop aload pop}\n");
  1749. X   writestring(" {pop cvx}ifelse}{pop cvx}ifelse}ifelse}bind def\n");
  1750. X   writestring("/pstopsmatrix matrix currentmatrix def\n");
  1751. X   writestring("/defaultmatrix{pstopsmatrix exch copy}bind def\n");
  1752. X   writestring("/initmatrix{matrix defaultmatrix setmatrix}bind def\n");
  1753. X   writestring("/pathtoproc{[{currentpoint}stopped{$error/newerror false\n");
  1754. X   writestring(" put{newpath}}{/newpath cvx 3 1 roll/moveto cvx 4 array\n");
  1755. X   writestring(" astore cvx}ifelse]{[/newpath cvx{/moveto cvx}{/lineto cvx}\n");
  1756. X   writestring(" {/curveto cvx}{/closepath cvx}pathforall]cvx exch pop}\n");
  1757. X   writestring(" stopped{$error/errorname get/invalidaccess eq{cleartomark\n");
  1758. X   writestring(" $error/newerror false put cvx exec}{stop}ifelse}if}def\n");
  1759. X   if (width > 0.0 && height > 0.0) {
  1760. X      char buffer[BUFSIZ];
  1761. X      writestring("/initclip[/pathtoproc lcvx/matrix lcvx/currentmatrix lcvx");
  1762. X      writestring("/initmatrix lcvx/initclip lcvx /newpath lcvx\n");
  1763. X      writestring(" 0 0 /moveto lcvx\n");
  1764. X      sprintf(buffer,
  1765. X          " %lf 0/rlineto lcvx 0 %lf/rlineto lcvx -%lf 0/rlineto lcvx\n",
  1766. X          width, height, width);
  1767. X      writestring(buffer);
  1768. X      writestring(" /clip lcvx /newpath lcvx /setmatrix lcvx /exec lcvx]\n");
  1769. X      writestring(" cvx def\n");
  1770. X   }
  1771. X   writestring("/initgraphics{initmatrix newpath initclip 1 setlinewidth\n");
  1772. X   writestring(" 0 setlinecap 0 setlinejoin []0 setdash 0 setgray\n");
  1773. X   writestring(" 10 setmiterlimit}bind def\n");
  1774. X   if (nobinding) /* desperation measures */
  1775. X      writestring("/bind{}def\n");
  1776. X   writestring("%%EndProcSet\n");
  1777. X   writeprolog();
  1778. X   for (thispg = 0; thispg < maxpage; thispg += modulo) {
  1779. X      int ppp, add_last = 0;
  1780. X      struct pagespec *ps;
  1781. X      for (ppp = 0, ps = specs; ps != NULL; ppp++, ps = ps->next) {
  1782. X     int actualpg;
  1783. X     int add_next = ((ps->flags & ADD_NEXT) != 0);
  1784. X     if (ps->reversed)
  1785. X        actualpg = maxpage-thispg-modulo+ps->pageno;
  1786. X     else
  1787. X        actualpg = thispg+ps->pageno;
  1788. X     if (actualpg < pages)
  1789. X        seekpage(actualpg);
  1790. X     if (!add_last) {
  1791. X        writepageheader("pstops", ++pageindex);
  1792. X     }
  1793. X     writestring("gsave\n");
  1794. X     if (ps->flags & GSAVE) {
  1795. X        char buffer[BUFSIZ];
  1796. X        if (ps->flags & OFFSET) {
  1797. X           sprintf(buffer, "%lf %lf translate\n", ps->xoff, ps->yoff);
  1798. X           writestring(buffer);
  1799. X        }
  1800. X        if (ps->flags & ROTATE) {
  1801. X           sprintf(buffer, "%d rotate\n", ps->rotate);
  1802. X           writestring(buffer);
  1803. X        }
  1804. X        if (ps->flags & SCALE) {
  1805. X           sprintf(buffer, "%lf dup scale\n", ps->scale);
  1806. X           writestring(buffer);
  1807. X        }
  1808. X        writestring("/pstopsmatrix matrix currentmatrix def\n");
  1809. X     }
  1810. X     if (width > 0.0 && height > 0.0) {
  1811. X        writestring("initclip\n");
  1812. X     }
  1813. X     writestring("/pstopssaved save def\n");
  1814. X     if (add_next) {
  1815. X        writestring("/showpage{}def/copypage{}def/erasepage{}def\n");
  1816. X     }
  1817. X     if (actualpg < pages)
  1818. X        writepagebody();
  1819. X     else
  1820. X        writestring("showpage\n");
  1821. X     writestring("pstopssaved restore grestore\n");
  1822. X     add_last = add_next;
  1823. X      }
  1824. X   }
  1825. X   writetrailer();
  1826. X
  1827. X   exit(0);
  1828. X}
  1829. END_OF_pstops.c
  1830. if test 9273 -ne `wc -c <pstops.c`; then
  1831.     echo shar: \"pstops.c\" unpacked with wrong size!
  1832. fi
  1833. # end of overwriting check
  1834. fi
  1835. if test -f psutil.c -a "${1}" != "-c" ; then 
  1836.   echo shar: Will not over-write existing file \"psutil.c\"
  1837. else
  1838. echo shar: Extracting \"psutil.c\" \(5220 characters\)
  1839. sed "s/^X//" >psutil.c <<'END_OF_psutil.c'
  1840. X/* psutil.c
  1841. X * AJCD 29/1/91
  1842. X * utilities for PS programs
  1843. X */
  1844. X
  1845. X#define LOCAL
  1846. X#include "psutil.h"
  1847. X
  1848. X#include <fcntl.h>
  1849. X#include <ctype.h>
  1850. X#include <string.h>
  1851. X
  1852. Xstatic char buffer[BUFSIZ];
  1853. Xstatic long bytes = 0;
  1854. Xstatic long pagescmt = 0;
  1855. Xstatic long headerlen = 0;
  1856. Xstatic int outputpage = 0;
  1857. Xstatic char pagelabel[BUFSIZ];
  1858. Xstatic int pageno;
  1859. Xstatic long pagelength;
  1860. X
  1861. X/* make a file seekable; trick stolen from Chris Torek's libdvi */
  1862. X
  1863. XFILE *seekable(fp)
  1864. X     FILE *fp;
  1865. X{
  1866. X   int fd, tf, n, w;
  1867. X   char *tmpdir, *p;
  1868. X
  1869. X   fd = fileno(fp);
  1870. X   if (lseek(fd, 0L, 1) >= 0 && !isatty(fd))
  1871. X      return (fp);
  1872. X
  1873. X   if ((tmpdir = getenv("TMPDIR")) == NULL)
  1874. X      tmpdir = TMPDIR;
  1875. X   (void) sprintf(buffer, "%s/#%d", tmpdir, getpid());
  1876. X   if ((tf = open(buffer, O_RDWR | O_CREAT | O_EXCL, 0666)) == -1)
  1877. X      return (NULL);
  1878. X   (void) unlink(buffer);
  1879. X
  1880. X   while ((n = read(fd, p = buffer, BUFSIZ)) > 0) {
  1881. X      do {
  1882. X     if ((w = write(tf, p, n)) < 0) {
  1883. X        (void) close(tf);
  1884. X        (void) fclose(fp);
  1885. X        return (NULL);
  1886. X     }
  1887. X     p += w;
  1888. X      } while ((n -= w) > 0);
  1889. X   }
  1890. X   if (n < 0) {
  1891. X      (void) close(tf);
  1892. X      (void) fclose(fp);
  1893. X      return (NULL);
  1894. X   }
  1895. X
  1896. X   /* discard the input file, and rewind and open the temporary */
  1897. X   (void) fclose(fp);
  1898. X   (void) lseek(tf, 0L, 0);
  1899. X   if ((fp = fdopen(tf, "r")) == NULL) {
  1900. X      (void) close(tf);
  1901. X   }
  1902. X   return (fp);
  1903. X}
  1904. X
  1905. X
  1906. Xint fcopy(len)
  1907. X     long len;
  1908. X{
  1909. X   while (len) {
  1910. X      int n = (len > BUFSIZ) ? BUFSIZ : len;
  1911. X      if (!(fread(buffer, sizeof(char), n, infile) &&
  1912. X        fwrite(buffer, sizeof(char), n, outfile)))
  1913. X     return (0);
  1914. X      len -= n;
  1915. X      bytes += n;
  1916. X   }
  1917. X   return (1);
  1918. X}
  1919. X
  1920. X/* build array of pointers to start/end of pages */
  1921. X
  1922. Xscanpages()
  1923. X{
  1924. X   register char *comment = buffer+2;
  1925. X   register int nesting = 0;
  1926. X
  1927. X   pages = 0;
  1928. X   fseek(infile, 0L, 0);
  1929. X   while (fgets(buffer, BUFSIZ, infile) != NULL)
  1930. X      if (*buffer == '%') {
  1931. X     if (buffer[1] == '%') {
  1932. X        if (strncmp(comment, "Page:", 5) == 0)
  1933. X           pageptr[pages++] = ftell(infile)-strlen(buffer);
  1934. X        else if (headerlen == 0 && strncmp(comment, "Pages:", 6) == 0)
  1935. X           pagescmt = ftell(infile)-strlen(buffer);
  1936. X        else if (headerlen == 0 &&
  1937. X             strncmp(comment, "EndComments", 11) == 0)
  1938. X           headerlen = ftell(infile);
  1939. X        else if (strncmp(comment, "BeginDocument", 13) == 0)
  1940. X           nesting++;
  1941. X        else if (strncmp(comment, "EndDocument", 11) == 0)
  1942. X           nesting--;
  1943. X        else if (strncmp(comment, "BeginBinary", 11) == 0)
  1944. X           nesting++;
  1945. X        else if (strncmp(comment, "EndBinary", 9) == 0)
  1946. X           nesting--;
  1947. X        else if (nesting == 0 && strncmp(comment, "Trailer", 7) == 0) {
  1948. X           fseek(infile, (long)(-strlen(buffer)), 1);
  1949. X           break;
  1950. X        }
  1951. X     } else if (headerlen == 0 && buffer[1] != '!')
  1952. X        headerlen = ftell(infile)-strlen(buffer);
  1953. X      }
  1954. X   pageptr[pages] = ftell(infile);
  1955. X}
  1956. X
  1957. Xseekpage(p)
  1958. X     int p;
  1959. X{
  1960. X   fseek(infile, pageptr[p], 0);
  1961. X   if (fgets(buffer, BUFSIZ, infile) != NULL &&
  1962. X       sscanf(buffer, "%%%%Page: %s %d\n", pagelabel, &pageno) == 2) {
  1963. X      pagelength = pageptr[p+1]-pageptr[p]-strlen(buffer);
  1964. X   } else {
  1965. X      fprintf(stderr, "%s: I/O error seeking page %d\n", prog, p);
  1966. X      fflush(stderr);
  1967. X      exit(1);
  1968. X   }
  1969. X}
  1970. X
  1971. Xwritestring(s)
  1972. X     char *s;
  1973. X{
  1974. X   fputs(s, outfile);
  1975. X   bytes += strlen(s);
  1976. X}
  1977. X
  1978. Xwritepageheader(label, page)
  1979. X     char *label;
  1980. X     int page;
  1981. X{
  1982. X   if (verbose) {
  1983. X      sprintf(buffer, "[%d] ", page);
  1984. X      message(buffer);
  1985. X   }
  1986. X   sprintf(buffer, "%%%%Page: %s %d\n", label, ++outputpage);
  1987. X   writestring(buffer);
  1988. X}
  1989. X
  1990. Xwritepagebody()
  1991. X{
  1992. X   if (!fcopy(pagelength)) {
  1993. X      fprintf(stderr, "%s: I/O error writing page %d\n", prog, outputpage);
  1994. X      fflush(stderr);
  1995. X      exit(1);
  1996. X   }
  1997. X}
  1998. X
  1999. Xwritepage(p)
  2000. X     int p;
  2001. X{
  2002. X   seekpage(p);
  2003. X   writepageheader(pagelabel, p+1);
  2004. X   writepagebody();
  2005. X}
  2006. X
  2007. X/* write header: should alter %%Pages: comment */
  2008. Xwriteheader(p)
  2009. X     int p;
  2010. X{
  2011. X   long len = headerlen;
  2012. X   fseek(infile, 0L, 0);
  2013. X   if (pagescmt && pagescmt < len) {
  2014. X      if (!fcopy(pagescmt) || fgets(buffer, BUFSIZ, infile) == NULL) {
  2015. X     fprintf(stderr, "%s: I/O error in header\n", prog);
  2016. X     fflush(stderr);
  2017. X     exit(1);
  2018. X      }
  2019. X      len -= pagescmt+strlen(buffer);
  2020. X      sprintf(buffer, "%%%%Pages: %d 0\n", p);
  2021. X      writestring(buffer);
  2022. X   }
  2023. X   if (!fcopy(len)) {
  2024. X      fprintf(stderr, "%s: I/O error in header\n", prog);
  2025. X      fflush(stderr);
  2026. X      exit(1);
  2027. X   }
  2028. X}
  2029. X
  2030. X
  2031. Xwriteprolog()
  2032. X{
  2033. X   if (!fcopy(pageptr[0]-headerlen)) {
  2034. X      fprintf(stderr, "%s: I/O error in prologue\n", prog);
  2035. X      fflush(stderr);
  2036. X      exit(1);
  2037. X   }
  2038. X}
  2039. X
  2040. X/* write trailer */
  2041. Xwritetrailer()
  2042. X{
  2043. X   fseek(infile, pageptr[pages], 0);
  2044. X   while (fgets(buffer, BUFSIZ, infile) != NULL) {
  2045. X      writestring(buffer);
  2046. X   }
  2047. X   if (verbose) {
  2048. X      sprintf(buffer, "Wrote %d pages, %ld bytes\n", outputpage, bytes);
  2049. X      message(buffer);
  2050. X   }
  2051. X}
  2052. X
  2053. X/* write message to stderr */
  2054. Xmessage(s)
  2055. X     char *s;
  2056. X{
  2057. X   static int pos = 0;
  2058. X   char *nl = strchr(s, '\n');
  2059. X   int len = nl ? (nl-s) : strlen(s);
  2060. X
  2061. X   if (pos+len > 79 && (pos > 79 || len < 80)) {
  2062. X      fputc('\n', stderr);
  2063. X      pos = 0;
  2064. X   }
  2065. X   fputs(s, stderr);
  2066. X   fflush(stderr);
  2067. X   pos += len;
  2068. X}
  2069. X
  2070. X
  2071. Xint writeemptypage()
  2072. X{
  2073. X   if (verbose)
  2074. X      message("[*] ");
  2075. X   sprintf(buffer, "%%%%Page: * %d\nshowpage\n", ++outputpage);
  2076. X   writestring(buffer);
  2077. X}
  2078. X
  2079. END_OF_psutil.c
  2080. if test 5220 -ne `wc -c <psutil.c`; then
  2081.     echo shar: \"psutil.c\" unpacked with wrong size!
  2082. fi
  2083. # end of overwriting check
  2084. fi
  2085. if test -f psutil.h -a "${1}" != "-c" ; then 
  2086.   echo shar: Will not over-write existing file \"psutil.h\"
  2087. else
  2088. echo shar: Extracting \"psutil.h\" \(663 characters\)
  2089. sed "s/^X//" >psutil.h <<'END_OF_psutil.h'
  2090. X/* psutil.h
  2091. X * AJCD 29/1/91
  2092. X * utilities for PS programs
  2093. X */
  2094. X
  2095. X#include <stdio.h>
  2096. X
  2097. X#ifndef LOCAL
  2098. X#define LOCAL extern
  2099. X#endif
  2100. X
  2101. X#define TMPDIR "/tmp"
  2102. X#define MAXPAGES 5000 /* max pages in document */
  2103. X
  2104. XLOCAL char *prog;
  2105. XLOCAL long pageptr[MAXPAGES];
  2106. XLOCAL int pages;
  2107. XLOCAL int verbose;
  2108. XLOCAL FILE *infile;
  2109. XLOCAL FILE *outfile;
  2110. X
  2111. XLOCAL FILE *seekable();
  2112. XLOCAL int fcopy();
  2113. XLOCAL writepage();
  2114. XLOCAL seekpage();
  2115. XLOCAL writepageheader();
  2116. XLOCAL writepagebody();
  2117. XLOCAL writeheader();
  2118. XLOCAL writeprolog();
  2119. XLOCAL writetrailer();
  2120. XLOCAL writeemptypage();
  2121. XLOCAL scanpages();
  2122. XLOCAL writestring();
  2123. XLOCAL message();
  2124. X
  2125. Xextern long lseek();
  2126. Xextern long ftell();
  2127. Xextern char *getenv();
  2128. END_OF_psutil.h
  2129. if test 663 -ne `wc -c <psutil.h`; then
  2130.     echo shar: \"psutil.h\" unpacked with wrong size!
  2131. fi
  2132. # end of overwriting check
  2133. fi
  2134. if test -f showchar -a "${1}" != "-c" ; then 
  2135.   echo shar: Will not over-write existing file \"showchar\"
  2136. else
  2137. echo shar: Extracting \"showchar\" \(2472 characters\)
  2138. sed "s/^X//" >showchar <<'END_OF_showchar'
  2139. X#!/bin/sh
  2140. X# showchar: show character with information
  2141. X# usage:
  2142. X#       showchar Font-Name Char-Name | lpr -Pprinter
  2143. X
  2144. Xif [ $# != 2 ]; then
  2145. X        echo "Usage: `basename $0` Font-Name Char-Name" >&2
  2146. X        exit 1
  2147. Xfi
  2148. X
  2149. Xcat <<EOF
  2150. X%!
  2151. X% Get character metrics and bounding box for $1
  2152. X/ns 30 string def
  2153. X/fname /$1 def
  2154. X/cname /$2 def
  2155. X/fn fname findfont 1000 scalefont def
  2156. X/thin 0.7 def
  2157. X/reduction 2.0 def
  2158. X
  2159. X/sn { ns cvs show } def
  2160. X/sc { (\()show exch sn (,)show sn (\))show } def
  2161. X
  2162. X/Times-Roman findfont 10 scalefont setfont
  2163. X
  2164. X72 288 translate % one inch in
  2165. Xnewpath 0 0 moveto
  2166. Xgsave   % print character name
  2167. X   0 432 rmoveto
  2168. X   ($2 from font $1 displayed on `date` by `basename $0` 1.00 (C) AJCD 1991)
  2169. X   show 
  2170. Xgrestore
  2171. X
  2172. Xgsave
  2173. X   thin setlinewidth  % cross hairs
  2174. X   -9 0 rmoveto 18 0 rlineto
  2175. X   -9 -9 rmoveto 0 18 rlineto
  2176. X   stroke  % position info
  2177. X   -9 -9 moveto ((0,0)) stringwidth pop neg 0 rmoveto
  2178. X   ((0,0)) show
  2179. Xgrestore
  2180. X
  2181. X% create encoding with a single character at all positions
  2182. X/MyEncoding 256 array def
  2183. X
  2184. X0 1 255 { % fill out with notdefs
  2185. X   MyEncoding exch cname put
  2186. X} for
  2187. X
  2188. Xfn dup length dict begin
  2189. X  {1 index /FID ne {def} {pop pop} ifelse} forall
  2190. X  /Encoding MyEncoding def
  2191. X  currentdict
  2192. Xend /newfont exch definefont
  2193. X/fn exch def
  2194. X/en MyEncoding def
  2195. X
  2196. Xgsave  % draw character (enlarged)
  2197. X  .75 setgray
  2198. X  fn 1 reduction div scalefont setfont
  2199. X  (\000) show
  2200. Xgrestore
  2201. X
  2202. X% show character info
  2203. Xfn /Metrics known {
  2204. X   dup fn /Metrics get exch get 
  2205. X   dup type /arraytype eq {
  2206. X      dup length 2 eq
  2207. X      {1 get} {2 get} ifelse
  2208. X   } if
  2209. X} {
  2210. X   gsave
  2211. X      fn setfont (\000) stringwidth pop round
  2212. X   grestore
  2213. X} ifelse
  2214. Xgsave   % show width
  2215. X   thin setlinewidth
  2216. X   dup reduction div 0 rlineto
  2217. X   gsave
  2218. X      1 1 rmoveto 0 sc
  2219. X   grestore
  2220. X   -4 -3 rlineto 0 6 rmoveto 4 -3 rlineto
  2221. X   stroke
  2222. Xgrestore
  2223. X
  2224. Xgsave
  2225. X   gsave  % get bounding box
  2226. X      fn setfont
  2227. X      (\000) true charpath flattenpath pathbbox
  2228. X   grestore
  2229. X   thin setlinewidth
  2230. X   3 index reduction div  % put coords on top of stack
  2231. X   3 index reduction div
  2232. X   3 index reduction div
  2233. X   3 index reduction div
  2234. X   3 index 3 index moveto
  2235. X   gsave  % llx lly
  2236. X      0 -9 rmoveto 7 index 7 index sc
  2237. X   grestore
  2238. X   1 index 3 index lineto
  2239. X   gsave  % urx lly
  2240. X      0 -9 rmoveto 5 index 7 index sc
  2241. X   grestore
  2242. X   1 index 1 index lineto
  2243. X   gsave  % urx ury
  2244. X      0 9 rmoveto 5 index 5 index sc
  2245. X   grestore
  2246. X   3 index 1 index lineto
  2247. X   gsave  % llx ury
  2248. X      0 9 rmoveto 7 index 5 index sc
  2249. X   grestore
  2250. X   closepath stroke
  2251. Xgrestore
  2252. Xshowpage
  2253. XEOF
  2254. END_OF_showchar
  2255. if test 2472 -ne `wc -c <showchar`; then
  2256.     echo shar: \"showchar\" unpacked with wrong size!
  2257. fi
  2258. chmod +x showchar
  2259. # end of overwriting check
  2260. fi
  2261. echo shar: End of archive 1 \(of 2\).
  2262. cp /dev/null ark1isdone
  2263. MISSING=""
  2264. for I in 1 2 ; do
  2265.     if test ! -f ark${I}isdone ; then
  2266.     MISSING="${MISSING} ${I}"
  2267.     fi
  2268. done
  2269. if test "${MISSING}" = "" ; then
  2270.     echo You have unpacked both archives.
  2271.     rm -f ark[1-9]isdone
  2272. else
  2273.     echo You still need to unpack the following archives:
  2274.     echo "        " ${MISSING}
  2275. fi
  2276. ##  End of shell archive.
  2277. exit 0
  2278.  
  2279. exit 0 # Just in case...
  2280.